/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package JFreeChartExtensions.chartextensions.crosshair;

import JFreeChartExtensions.ExtendableChartPanel;
import JFreeChartExtensions.chartextensions.IChartExtensionManager;
import JFreeChartExtensions.listeners.ExtendedChartProgresListener;
import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.ValueMarker;
import org.jfree.chart.plot.XYPlot;
import org.jfree.ui.LengthAdjustmentType;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.RectangleInsets;
import org.jfree.ui.TextAnchor;

/**
 *
 * @author Nobody
 */
public class CrossHairManager implements ChartMouseListener, ExtendedChartProgresListener, IChartExtensionManager, FocusListener {

    @Override
    public void focusGained(FocusEvent e) {
        setEnableTracing(true);
    }

    @Override
    public void focusLost(FocusEvent e) {
        setEnableTracing(false);
    }

    public void setAttractToPoints(boolean attractToPoints) {
        this.attractToPoints = attractToPoints;
    }

    public void setShowDomainMarker(boolean showDomainMarker) {
        this.showDomainMarker = showDomainMarker;
    }

    public void setShowRangeMarker(boolean showRangeMarker) {
        this.showRangeMarker = showRangeMarker;
    }

    public boolean isAttractToPoints() {
        return attractToPoints;
    }

    public boolean isShowDomainMarker() {
        return showDomainMarker;
    }

    public boolean isShowRangeMarker() {
        return showRangeMarker;
    }

    @Override
    public void register(ChartPanel chartPanel) {
        this.chartPanel = (ExtendableChartPanel) chartPanel;
        ((ExtendableChartPanel) chartPanel).addChartProgressListener(this);
        ((ExtendableChartPanel) chartPanel).addChartMouseListener(this);
    }

    @Override
    public void unregister() {
        chartPanel.removeChartMouseListener(this);
        chartPanel.removeChartProgessListener(this);
    }

    @Override
    public void chartChanged(ExtendableChartPanel aThis) {
        if (attractToPoints) {
            if (aThis.getXYPlot().getDomainCrosshairValue() == chartX
                    && aThis.getXYPlot().getRangeCrosshairValue() == chartY) {
                return;
            }
            chartY = aThis.getXYPlot().getRangeCrosshairValue();
            chartX = aThis.getXYPlot().getDomainCrosshairValue();
            drawLabel(aThis.getChart());
        }
    }
    ValueMarker lastUsedDomainMarker;
    ValueMarker lastUsedRangeMarker;
    ExtendableChartPanel chartPanel;
    private double chartX = -1.0;
    private double chartY = -1.0;
    private boolean attractToPoints;
    private boolean showRangeMarker;
    private boolean showDomainMarker;
    private Color lineColor = Color.BLACK;
    private Color labelColor = Color.WHITE;

    public Color getLabelColor() {
        return labelColor;
    }

    public void setLabelColor(Color labelColor) {
        this.labelColor = labelColor;
    }

    public Color getLineColor() {
        return lineColor;
    }

    public void setLineColor(Color lineColor) {
        this.lineColor = lineColor;
    }

    public CrossHairManager(ExtendableChartPanel chartPanel, boolean attractToPoints, boolean showRangeMarker, boolean showDomainMarker) {
        this.chartPanel = chartPanel;
        this.attractToPoints = attractToPoints;
        this.showDomainMarker = showDomainMarker;
        this.showRangeMarker = showRangeMarker;
        chartPanel.addFocusListener(this);
        setEnableTracing(true);
    }

    private void setEnableTracing(boolean value) {
        chartPanel.setHorizontalAxisTrace(value);
        chartPanel.setVerticalAxisTrace(value);
    }

    private void getCoordinates(ChartMouseEvent cme) {
        Point2D p = cme.getTrigger().getPoint();
        XYPlot plot = cme.getChart().getXYPlot();
        ValueAxis domainAxis = plot.getDomainAxis();
        ValueAxis rangeAxis = plot.getRangeAxis();
        chartX = domainAxis.java2DToValue(p.getX(), chartPanel.getScreenDataArea(), plot.getDomainAxisEdge());
        chartY = rangeAxis.java2DToValue(p.getY(), chartPanel.getScreenDataArea(), plot.getRangeAxisEdge());

    }

    public void update() {
        if (lastUsedDomainMarker != null) {
            lastUsedDomainMarker.setPaint(lineColor);
            lastUsedDomainMarker.setLabelPaint(labelColor);
        }
        if (lastUsedRangeMarker != null) {
            lastUsedRangeMarker.setPaint(lineColor);
            lastUsedRangeMarker.setLabelPaint(labelColor);
        }
        if (!showDomainMarker) {
            deleteLastDomainMarker(chartPanel.getXYPlot());
        }
        if (!showRangeMarker) {
            deleteLastRangeMarker(chartPanel.getXYPlot());
        }
        chartPanel.updateChart();
    }

    @Override
    public void chartMouseClicked(ChartMouseEvent cme) {

        if (cme.getTrigger().getButton() != MouseEvent.BUTTON1) {
            return;
        }
        if (!attractToPoints) {
            getCoordinates(cme);
            drawLabel(cme.getChart());
        }



    }

    private void drawLabel(JFreeChart chart) {
        if (showDomainMarker) {
            drawDomainLabel(chart);
        }
        if (showRangeMarker) {
            drawRangeLabel(chart);
        }
    }

    private void drawDomainLabel(JFreeChart chart) {
        deleteLastDomainMarker(chart.getXYPlot());
        ValueMarker marker = new ValueMarker(chartX);
        marker.setLabel(String.format("X: %-1.3f%sY: %-1.3f", chartX, "\n", chartY));
        marker.setLabelOffsetType(LengthAdjustmentType.EXPAND);
        marker.setPaint(lineColor);
        marker.setLabelPaint(labelColor);
        marker.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
        marker.setLabelTextAnchor(TextAnchor.TOP_LEFT);

        chart.getXYPlot().addDomainMarker(marker);
        lastUsedDomainMarker = marker;
    }

    private void drawRangeLabel(JFreeChart chart) {
        deleteLastRangeMarker(chart.getXYPlot());
        ValueMarker marker = new ValueMarker(chartY);
        marker.setLabel(String.format("X: %-1.3f%sY: %-1.3f", chartX, "\n\r", chartY));
        marker.setLabelOffsetType(LengthAdjustmentType.EXPAND);
        marker.setPaint(lineColor);
        marker.setLabelPaint(labelColor);
        marker.setLabelOffset(new RectangleInsets(10, 40, 0, 0));
        chart.getXYPlot().addRangeMarker(marker);
        lastUsedRangeMarker = marker;
    }

    private void deleteLastDomainMarker(XYPlot xyplot) {
        if (lastUsedDomainMarker != null) {
            xyplot.removeDomainMarker(lastUsedDomainMarker);
        }
    }

    private void deleteLastRangeMarker(XYPlot xyplot) {
        if (lastUsedRangeMarker != null) {
            xyplot.removeRangeMarker(lastUsedRangeMarker);
        }
    }

    @Override
    public void chartMouseMoved(ChartMouseEvent cme) {
    }
}
